package gfx;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import game.Game;
import util.GameClock;
import util.Logger;
import android.opengl.GLU;
import android.opengl.GLSurfaceView.Renderer;
import android.view.Menu;

public class GLRenderer implements Renderer{
//	private Menu menu;
	private Game game;
	
	private long lastFPSSecond;
	private int quickFPSMeter;
	
	private static boolean isLoaded;
	
	public GLRenderer(Game game){
		this.game = game;
	}

	@Override
	public void onDrawFrame(GL10 gl) {
		// TODO If I only use tick and getTick once, I can have tick return the time as well, and integrate them together.
		GameClock.getInstance().tick();
		
		gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
		game.update(GameClock.getInstance().getTick());
		if(!game.loadGraphics(gl))
			return;
		if(game.isReady()){
			gl.glPushMatrix();
			gl.glTranslatef(-Camera.GL_WIDTH/2, -Camera.GL_HEIGHT/2,  Camera.Z_DISTANCE);
			game.draw(gl);
			gl.glPopMatrix();
		}
		

		if(!Spritesheet.getInstance().isLoaded())
			Spritesheet.getInstance().loadAll(gl);
		 
		if(lastFPSSecond + 1000 < GameClock.getInstance().getCurrentTime()){
			Logger.log("FPS: " + quickFPSMeter);
			quickFPSMeter = 0;
			lastFPSSecond = GameClock.getInstance().getCurrentTime();
		}
		else ++quickFPSMeter;
	}

	@Override
	public void onSurfaceChanged(GL10 gl, int width, int height) {
    	gl.glViewport(0, 0, width, height); 	//Reset The Current Viewport
		gl.glMatrixMode(GL10.GL_PROJECTION); 	//Select The Projection Matrix
		gl.glLoadIdentity(); 					//Reset The Projection Matrix

		GLU.gluPerspective(gl, Camera.FOVY, Camera.SCREEN_RATIO, 0.1f, 100.0f);

		gl.glMatrixMode(GL10.GL_MODELVIEW); 	//Select The Modelview Matrix
		gl.glLoadIdentity(); 					//Reset The Modelview Matrix
	}

	@Override
	public void onSurfaceCreated(GL10 gl, EGLConfig config) {
		GameClock.getInstance();

		Spritesheet.getInstance().loadSplash(gl);
		Spritesheet.getInstance().setLoaded(false);
		
//		Spritesheet.getInstance().loadAll(gl);
		
		quickFPSMeter = 0;
		lastFPSSecond = GameClock.getInstance().getCurrentTime();
		
		//Load textures here, everytime this is run
		//it means that open gl context has been destroyed
		//i.e... all textures are gone, and need to be reloaded
		//so everytime onPause/onResume
		boolean supportsDrawTexture = gl.glGetString(GL10.GL_EXTENSIONS).contains("draw_texture");
		int[] maxTextureSize = new int[1];
		gl.glGetIntegerv(GL10.GL_MAX_TEXTURE_SIZE, maxTextureSize, 0);
		Logger.log("[GameRenderer]: Supports draw texture: " + supportsDrawTexture);
		Logger.log("[GameRenderer]: Max Texture Size: " + maxTextureSize[0]);
		
		//mMenu.load();
//		Font.load(gl);
			
		gl.glEnable(GL10.GL_CULL_FACE);				// Culling
		gl.glCullFace(GL10.GL_BACK);

		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST);
		
		gl.glEnable(GL10.GL_TEXTURE_2D);			// Mapping
		gl.glShadeModel(GL10.GL_SMOOTH);			// Smooth Shading
		gl.glClearColor(0.0f, 0.0f, 0.0f, 1f);		// Color BG
		gl.glClearDepthf(1.0f);						// Depth Buffer Setup
		gl.glEnable(GL10.GL_DEPTH_TEST);			// Depth Testing
		gl.glDepthFunc(GL10.GL_LEQUAL);				// Type of Depth Test

		// For Transparency
		gl.glEnable(GL10.GL_BLEND);
		gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);

		// Perspective Calculations
		gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
		
		isLoaded = true;
	}

	public static boolean isLoaded(){ return isLoaded; }
}
